package io.mft.dev.base.config.builder;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import io.mft.api.domain.ApiFunctionType;
import io.mft.commons.config.ConfigProvider;
import io.mft.commons.exception.MFTException;
import io.mft.dev.base.ApiThreadExecutorConfig;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class CatalogApiBuilder {
	private ClassLoader classLoader;
	@Setter
	@Getter
	public static class CatalogApi{
		private String key;
		private String desc;
		private int workQueueCapacity = 0;
		private int maxPoolSize = 0;
		private String systemKey;
		private String moduleKey;
		private ApiFunctionType apiFunctionType;
	}
	
	@Getter
	public static class CatalogApiCollection{
		private final List<CatalogApi> catalogApis=new ArrayList<>();
		private final  List<ApiThreadExecutorConfig> apiThreadExecutorConfigs=new ArrayList<>();
	}
	

	public CatalogApiBuilder(ClassLoader classLoader) {
		this.classLoader=classLoader;
	}
	public CatalogApiCollection build(){
		CatalogApiCollection catalogApiCollection=new CatalogApiCollection();
		Map<String, Object> map=ConfigProvider.getNamespaceConfigObject(classLoader,"apiCatalog");
		if (map==null) {
			return catalogApiCollection;
		}
		map.keySet().forEach(systemKey->{
			try {
				Map<String, Object> moduleMap=ConfigProvider.getMapValue(map, systemKey);
				moduleMap.keySet().forEach(moduleKey->{
					try {
						Map<String, Object> configMap=ConfigProvider.getMapValue(moduleMap, moduleKey);
						Map<String, Object> apiThreadExecutorMap=ConfigProvider.getMapValue(configMap, "apiThreadExecutor");
						if (apiThreadExecutorMap!=null) {
							ApiThreadExecutorConfig apiThreadExecutorConfig=BeanUtil.toBean(apiThreadExecutorMap, ApiThreadExecutorConfig.class);
							apiThreadExecutorConfig.setSystemKey(systemKey);
							apiThreadExecutorConfig.setModuleKey(moduleKey);
							catalogApiCollection.getApiThreadExecutorConfigs().add(apiThreadExecutorConfig);
						}
						Map<String, Object> apiFunctionTypeMap=ConfigProvider.getMapValue(configMap, "apis");
						apiFunctionTypeMap.keySet().forEach(apiFunctionType->{
							try {
								List<Map<String, Object>> apiList=ConfigProvider.getMapValue(apiFunctionTypeMap, apiFunctionType);
								apiList.forEach(a->{
									try {
										CatalogApi catalogApi=BeanUtil.toBean(a, CatalogApi.class);
										catalogApi.setSystemKey(systemKey);
										catalogApi.setApiFunctionType(ApiFunctionType.valueOf(apiFunctionType));
										catalogApi.setModuleKey(moduleKey);
										if (catalogApi.getMaxPoolSize()>0) {
											ApiThreadExecutorConfig threadExecutorConfig=new ApiThreadExecutorConfig();
											threadExecutorConfig.setCode(catalogApi.getKey());
											threadExecutorConfig.setMaxPoolSize(catalogApi.getMaxPoolSize());
											threadExecutorConfig.setWorkQueueCapacity(catalogApi.getWorkQueueCapacity());
											threadExecutorConfig.setSystemKey(systemKey);
											threadExecutorConfig.setModuleKey(moduleKey);
											catalogApiCollection.getApiThreadExecutorConfigs().add(threadExecutorConfig);
										}
										catalogApiCollection.getCatalogApis().add(catalogApi);
									} catch (Exception e) {
										log.error("系统["+systemKey+"]模块["+moduleKey+"]接口分类["+apiFunctionType+"]接口["+JSONUtil.toJsonStr(a)+"]目录处理异常,请检查",e);
									}
								});
							} catch (Exception e) {
								log.error("系统["+systemKey+"]模块["+moduleKey+"]接口分类["+apiFunctionType+"]接口目录处理异常,请检查",e);
							}
						});
					} catch (Exception e) {
						log.error("系统["+systemKey+"]模块["+moduleKey+"]接口目录处理异常,请检查",e);
					}
				});
			} catch (Exception e) {
				log.error("系统["+systemKey+"]接口目录处理异常,请检查",e);
			}
		});
		Map<String, CatalogApi> apiMap=new HashMap<String, CatalogApi>();
		catalogApiCollection.getCatalogApis().forEach(api->{
			if (apiMap.containsKey(api.getKey())) {
				try {
					String apiPath=api.getSystemKey()+"."+api.getModuleKey()+"."+api.getApiFunctionType()+"."+api.getKey();
					String apiPath0=apiMap.get(api.getKey()).getSystemKey()+"."+apiMap.get(api.getKey()).getModuleKey()+"."+apiMap.get(api.getKey()).getApiFunctionType()+"."+apiMap.get(api.getKey()).getKey();
					throw new MFTException(-1,"接口目录apiCatalog不允许配置相同API,请检查["+apiPath+"]["+apiPath0+"]"); 
				} catch (Exception e) {
					log.error("",e);
				}
			}else {
				apiMap.put(api.getKey(), api);
			}
		});
		return catalogApiCollection;
	}
}
